package com.cjd.view

import android.animation.ObjectAnimator
import android.animation.TypeEvaluator
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.TypedArray
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.animation.LinearInterpolator
import android.widget.TextView
import com.cjd.common.R
import com.cjd.common.utils.LogUtils
import kotlin.math.max
import kotlin.math.min

/**
 * @Author chenjidong
 * @email 374122600@qq.com
 * created 2019/9/23
 * description 水波纹 根据模式可调整 收缩 或外扩方式
 */
@SuppressLint("AppCompatCustomView")
class RippleView @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0
) : TextView(context, attributeSet, defStyleAttr) {

    companion object {
        @JvmStatic
        val MODE_IN = 1 //收缩
        @JvmStatic
        val MODE_OUT = 2 //外扩
    }

    /**
     * 波纹的颜色
     */
    var mRippleColor = Color.parseColor("#ff0000")
    /**
     * 默认的波纹的最小值
     */
    private val mMinSize = 200
    /**
     * 波纹动画效果是否正在进行
     */
    private var animationRunning = false

    private var currentProgress = 0
    /**
     * 动画中波纹的个数
     */
    private var mRippleNum = 4
    /**
     * 无限长的数值，使动画不停止
     */
    private var mTotalTime = 1000L * 1000L


    /**
     * 波纹模式
     */
    private var mode = MODE_OUT

    private val mPeriod = 30
    private var mCenterX: Int = 0
    private var mCenterY: Int = 0
    private var mRadius: Int = 0
    private var startAutoAminator = false

    fun setRippleColor(color: Int) {
        mRippleColor = color
        mPaint.color = mRippleColor
    }

    private val mPaint: Paint by lazy {
        Paint().apply {
            this.color = mRippleColor
            this.isAntiAlias = true
            this.style = Paint.Style.FILL
        }
    }
    private val mAnimator: ObjectAnimator by lazy {
        ObjectAnimator.ofInt(this@RippleView, "currentProgress", 0, 100).apply {
            this.repeatCount = ObjectAnimator.INFINITE
            this.repeatMode = ObjectAnimator.RESTART
            this.interpolator = LinearInterpolator()
            this.setEvaluator(mProgressEvaluator)
            this.duration = mTotalTime
        }
    }

    init {

        if (attributeSet != null) {
            val ta: TypedArray =
                context.obtainStyledAttributes(attributeSet, R.styleable.RippleView)
            mRippleColor =
                ta.getColor(R.styleable.RippleView_ripple_color, Color.parseColor("#ff0000"))
            mRippleNum = ta.getInteger(R.styleable.RippleView_ripple_num, 4)
            startAutoAminator = ta.getBoolean(R.styleable.RippleView_ripple_animator, false)
            mTotalTime = ta.getInteger(R.styleable.RippleView_ripple_duration, 1000 * 1000).toLong()
            ta.recycle()
        }

    }

    fun setMode(mode: Int) {
        this.mode = mode
    }

    fun startRippleAnimation() {
        if (!animationRunning) {
            mAnimator.start()
            animationRunning = true
        }
    }

    fun stopRippleAnimation() {
        if (animationRunning) {
            mAnimator.end()
            animationRunning = false
        }
    }

    fun getCurrentProgress(): Int {
        return currentProgress
    }

    fun setCurrentProgress(currentProgress: Int) {
        this.currentProgress = currentProgress
        this.invalidate()
    }

    private fun isRippleAnimationRunning(): Boolean {
        return animationRunning
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        var resultWidth = 0
        val modeWidth = MeasureSpec.getMode(widthMeasureSpec)
        val sizeWidth = MeasureSpec.getSize(widthMeasureSpec)
        if (modeWidth == MeasureSpec.EXACTLY) {
            resultWidth = sizeWidth
        } else {
            resultWidth = mMinSize
            if (modeWidth == MeasureSpec.AT_MOST) {
                resultWidth = min(resultWidth, sizeWidth)
            }
        }

        var resultHeight = 0
        val modeHeight = MeasureSpec.getMode(heightMeasureSpec)
        val sizeHeight = MeasureSpec.getSize(heightMeasureSpec)
        if (modeHeight == MeasureSpec.EXACTLY) {
            resultHeight = sizeHeight
        } else {
            resultHeight = mMinSize
            if (modeHeight == MeasureSpec.AT_MOST) {
                resultHeight = min(resultHeight, sizeHeight)
            }
        }

        mCenterX = resultWidth / 2
        mCenterY = resultHeight / 2
        mRadius = max(resultWidth, resultHeight) / 2

        LogUtils.d(
            "ripple out view radius = " + mRadius + "; width =" + resultWidth
                    + "; height = " + resultHeight
        )

        setMeasuredDimension(resultWidth, resultHeight)
    }

    public override fun onDraw(canvas: Canvas) {
        for (i in 0 until mRippleNum) {
            var progress = (currentProgress + i * 100 / mRippleNum) % 100
            if (mode == MODE_IN)
                progress = 100 - progress

            mPaint.alpha = 255 - 255 * progress / 100
            canvas.drawCircle(
                mCenterX.toFloat(),
                mCenterY.toFloat(),
                (mRadius * progress / 100).toFloat(),
                mPaint
            )
        }
        super.onDraw(canvas)
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        if (startAutoAminator)
            startRippleAnimation()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        if (isRippleAnimationRunning())
            stopRippleAnimation()
    }

    /**
     * 自定义估值器
     */
    private val mProgressEvaluator =
        TypeEvaluator<Int> { fraction, startValue, endValue ->
            val fraction = fraction * mTotalTime / mPeriod % 100
            fraction.toInt()
        }
}